#include "stdafx.h"
#include "TestUtils.h"
#include "Group.h"
#include "Helpers.h"
#include <iostream>
using namespace std;

TestUtils::TestResult TestUtils::VerifyIsTrue(bool cond, string message)
{
	if (!cond)
	{
		Debug::PrintDebugMsg(message);
		return TestUtils::TestFailed;
	}
	return TestUtils::TestPassed;
}

void TestUtils::PrintTestResult(string scenario, TestResult result)
{
	string resultStr;
	if (result==TestUtils::TestFailed)
	{
		resultStr = "FAILED";
	} else
	{
		resultStr = "Passed";
	}

	string str = "Test : " + scenario + " "  + resultStr;
	Debug::PrintDebugMsg(str);
}

//---------------------------------------------------------------------------------
// CreateGraph4On2
// Creates a graph with n=4, w=2
//---------------------------------------------------------------------------------
Graph& TestUtils::CreateGraph4On2(Graph& graph)
{
	VertexDirectory::Clear();
	set<vector<bool>> *vertices = VertexDirectory::CreateAllVertices(4,2);
	VertexDirectory::FillVertexDirectory(vertices);
	
	bool name1[] = {1,1,0,0};
	int n = 4;
	Vertex *v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name1,n));
	graph.InsertVertex(v);

	bool name2[] = {0,1,1,0};
	v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name2,n));
	graph.InsertVertex(v);

	bool name3[] = {0,0,1,1};
	v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name3,n));
	graph.InsertVertex(v);
	
	bool name4[] = {1,0,0,1};
	v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name4,n));
	graph.InsertVertex(v);

	bool name5[] = {0,1,0,1};
	v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name5,n));
	graph.InsertVertex(v);

	bool name6[] = {1,0,1,0};
	v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name6,n));
	graph.InsertVertex(v);
	
	return graph;
}

// Creates a graph with n=6, w=2, 
// creates a group containing 110000, 001100, 000011 in this order
Graph* TestUtils::CreateMaximalGroupAndGraph6On2(Group& group)
{
	Graph* graph = CreateGroupAndGraph6On2(group);
	bool name3[] = {0,0,0,0,1,1};
	int n = 6;
	Vertex* v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name3,n));
	graph->RemoveVertex(v);
	group.InsertNewVertex(v);
	return graph;
}

// Creates a graph with n=6, w=2, 
// creates a group containing 110000, 001100 in this order
Graph* TestUtils::CreateGroupAndGraph6On2(Group& group)
{
	int n = 6;
	Graph* graph = CreateMinimalGroupAndGraph6On2(group);
	bool name2[] = {0,0,1,1,0,0};
	Vertex* v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name2,n));
	graph->RemoveVertex(v);
	group.InsertNewVertex(v);
	return graph;
}

// Creates a graph with n=6, w=2, 
// creates a group containing 110000
Graph* TestUtils::CreateMinimalGroupAndGraph6On2(Group& group)
{
	CreateVertexDirectory(6,2);
	Graph* graph = CreateGraphFromDirectory(VertexDirectory::GetStaticCopyVertices(), NULL);
	bool name1[] = {1,1,0,0,0,0};
	int n = 6;
	Vertex *v = VertexDirectory::GetStaticCopyVertex(Vertex::GetNameFromArray(name1,n));
	graph->RemoveVertex(v);
	group.InsertNewVertex(v);
	return graph;
}

//---------------------------------------------------------------------------------
// CreateBigChain7On2With3Groups
// adds 3 groups to the given chain, of sizes 3,3,2.
//---------------------------------------------------------------------------------
Chain* TestUtils::CreateBigChain7On2With3Groups(Chain* chain)
{
	VertexDirectory* dir = chain->GetDirectory();
	if (dir == NULL)	// no vertex directory associated with this chain
	{
		return NULL;
	}
	Group* group = new Group(1, dir);
	bool name1[] = {0,0,0,1,1,1,1};
	int n = 7;
	Vertex *v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name1,n));
	group->InsertNewVertex(v);
	bool name2[] = {0,1,1,1,1,0,0};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name2,n));
	group->InsertNewVertex(v);
	bool name3[] = {1,1,0,0,0,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name3,n));
	group->InsertNewVertex(v);
	chain->AddGroup(group);
	
	Group* group2 = new Group(2, dir);
	bool name4[] = {1,1,1,1,0,0,0};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name4,n));
	group2->InsertNewVertex(v);
	bool name5[] = {0,0,1,1,0,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name5,n));
	group2->InsertNewVertex(v);
	bool name6[] = {1,0,0,1,1,1,0};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name6,n));
	group2->InsertNewVertex(v);
	chain->AddGroup(group2);

	Group* group3 = new Group(3, dir);
	bool name7[] = {1,0,1,1,1,0,0};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name7,n));
	group3->InsertNewVertex(v);
	bool name8[] = {0,1,0,0,1,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name8,n));
	group3->InsertNewVertex(v);
	chain->AddGroup(group3);

	return chain;
}

//---------------------------------------------------------------------------------
// CreateAnotherBigChain7On2With3Groups
// adds 3 groups to the given chain, of sizes 3,3,2. (these groups are different 
// than those created by CreateBigChain7On2With3Groups function)
//---------------------------------------------------------------------------------
Chain* TestUtils::CreateAnotherBigChain7On2With3Groups(Chain* chain)
{
	chain = CreateShortChain7On2With3Groups(chain);
	
	VertexDirectory* dir = chain->GetDirectory();
	if (dir == NULL)	// no vertex directory associated with this chain
	{
		return NULL;
	}
	Group* group = new Group(1, dir);
	bool name2[] = {1,1,0,0,0,1,1};
	int n = 7;
	Vertex* v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name2,n));
	group->InsertNewVertex(v);
	bool name3[] = {1,0,1,1,0,0,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name3,n));
	group->InsertNewVertex(v);
	chain->AddGroup(group);
	
	return chain;
}

//---------------------------------------------------------------------------------
// CreateBigLongChain7On2With3Groups
// adds 4 groups to the given chain, of sizes 3,3,2,1
//---------------------------------------------------------------------------------
Chain* TestUtils::CreateBigLongChain7On2With3Groups(Chain* chain)
{
	chain = CreateBigChain7On2With3Groups(chain);
	
	VertexDirectory* dir = chain->GetDirectory();
	if (dir == NULL)	// no vertex directory associated with this chain
	{
		return NULL;
	}
	Group* group = new Group(15, dir);
	bool name2[] = {0,1,0,1,0,1,1};
	int n = 7;
	Vertex* v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name2,n));
	group->InsertNewVertex(v);
	chain->AddGroup(group);
	
	return chain;
}

//---------------------------------------------------------------------------------
// CreateShortChain7On2With3Groups
// adds 2 groups to the given chain, of sizes 3,3.
//---------------------------------------------------------------------------------
Chain* TestUtils::CreateShortChain7On2With3Groups(Chain* chain)
{
	VertexDirectory* dir = chain->GetDirectory();
	if (dir == NULL)	// no vertex directory associated with this chain
	{
		return NULL;
	}
	Group* group2 = new Group(12, dir);
	bool name4[] = {1,1,1,1,0,0,0};
	int n = 7;
	Vertex* v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name4,n));
	group2->InsertNewVertex(v);
	bool name5[] = {0,0,1,1,0,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name5,n));
	group2->InsertNewVertex(v);
	bool name6[] = {1,0,0,1,1,1,0};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name6,n));
	group2->InsertNewVertex(v);
	chain->AddGroup(group2);

	Group* group3 = new Group(4, dir);
	bool name7[] = {1,0,1,1,1,0,0};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name7,n));
	group3->InsertNewVertex(v);
	bool name8[] = {0,1,0,0,1,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name8,n));
	group3->InsertNewVertex(v);
	bool name1[] = {0,0,0,1,1,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name1,n));
	group3->InsertNewVertex(v);
	chain->AddGroup(group3);

	return chain;
}

//---------------------------------------------------------------------------------
// CreateMixedBigChain7On2With3Groups
// adds 3 groups to the given chain, of sizes 3,2,3.
// Therefore, when compared with the groups created by 
// CreateAnotherBigChain7On2With3Groups & CreateBigChain7On2With3Groups chains, this
// chain will be smaller
//---------------------------------------------------------------------------------
Chain* TestUtils::CreateMixedBigChain7On2With3Groups(Chain* chain)
{
	VertexDirectory* dir = chain->GetDirectory();
	if (dir == NULL)	// no vertex directory associated with this chain
	{
		return NULL;
	}
	Group* group2 = new Group(12, dir);
	bool name4[] = {1,1,1,1,0,0,0};
	int n = 7;
	Vertex* v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name4,n));
	group2->InsertNewVertex(v);
	bool name5[] = {0,0,1,1,0,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name5,n));
	group2->InsertNewVertex(v);
	bool name6[] = {1,0,0,1,1,1,0};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name6,n));
	group2->InsertNewVertex(v);
	chain->AddGroup(group2);

	 Group* group = new Group(1, dir);
	bool name2[] = {1,1,0,0,0,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name2,n));
	group->InsertNewVertex(v);
	bool name3[] = {1,0,1,1,0,0,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name3,n));
	group->InsertNewVertex(v);
	chain->AddGroup(group);

	Group* group3 = new Group(4, dir);
	bool name7[] = {1,0,1,1,1,0,0};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name7,n));
	group3->InsertNewVertex(v);
	bool name8[] = {0,1,0,0,1,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name8,n));
	group3->InsertNewVertex(v);
	bool name1[] = {0,0,0,1,1,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name1,n));
	group3->InsertNewVertex(v);
	chain->AddGroup(group3);	

	return chain;
}


// adds 3 groups to the chain, of sizes 3,2,1
Chain* TestUtils::CreateSmallChain7On2With3Groups(Chain* chain)
{
	VertexDirectory* dir = chain->GetDirectory();
	if (dir == NULL)	// no vertex directory associated with this chain
	{
		return NULL;
	}
	Group* group = new Group(1, dir);
	int n = 7;
	Group* group2 = new Group(2, dir);
	bool name4[] = {1,1,1,1,0,0,0};
	Vertex *v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name4,n));
	group2->InsertNewVertex(v);
	bool name5[] = {0,0,1,1,0,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name5,n));
	group2->InsertNewVertex(v);
	bool name6[] = {1,0,0,1,1,1,0};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name6,n));
	group2->InsertNewVertex(v);
	chain->AddGroup(group2);

	Group* group3 = new Group(3, dir);
	bool name7[] = {1,0,1,1,1,0,0};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name7,n));
	group3->InsertNewVertex(v);
	bool name8[] = {0,1,0,0,1,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name8,n));
	group3->InsertNewVertex(v);
	chain->AddGroup(group3);

	Group* group1 = new Group(1, dir);
	bool name9[] = {0,0,0,1,1,1,1};
	v = dir->GetWorkingCopyVertex(Vertex::GetNameFromArray(name9,n));
	group1->InsertNewVertex(v);
	chain->AddGroup(group1);

	return chain;
}


// Fills the provided graph with all the vertices in vertices
// vertex pointers are taken from the Backup map in dir, if it is not NULL.
// if it is NULL, vertices are taken from the static vertex directory
Graph* TestUtils::CreateGraphFromDirectory(map<vector<bool>, Vertex*>* vertices, VertexDirectory* dir)
{
	Graph* graph = new Graph(100,100, dir);
	map<vector<bool>, Vertex*>::iterator it;
	for (it = vertices->begin(); it != vertices->end(); it++)
	{
		Vertex* v;
		if (dir == NULL)
		{	// use static directory
			v = VertexDirectory::GetStaticCopyVertex((*it).second->Name());
		}
		else
		{	// use provided directory
			v = dir->GetWorkingCopyVertex((*it).second->Name());
		}
		graph->InsertVertex(v);
	}
	return graph;
}

// creates the static directory over binary vectors with length n and weight w
void TestUtils::CreateVertexDirectory(int n, int w)
{
	VertexDirectory::Clear();
//	VertexDirectory::ClearAllVertexSets();
	set<vector<bool>> *vertices = VertexDirectory::CreateAllVertices(n,w);
	VertexDirectory::FillVertexDirectory(vertices);
}

// creates the vertices with length n and weight w, and add all of them to the graph
Graph* TestUtils::CreateGraphNOnW(int n, int w)
{
	CreateVertexDirectory(n,w);
	return CreateGraphFromDirectory(VertexDirectory::GetStaticCopyVertices(), NULL);
}

string TestUtils::GetVertexName(vector<bool> name)
{
	Vertex tempVertex = Vertex(name);
	return tempVertex.PrintName();
}

